package gameClient.view;

import gameClient.thread.*;
import gameClient.util.GameUtil;
import gameClient.model.Player;
import gameClient.model.Poker;
import gameClient.model.PokerLabel;
import gameClient.thread.*;
import gameClient.util.*;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.Socket;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.naming.InitialContext;

/**
 * 主窗体显示，如显示背景图片/出牌/抢地主等等
 */

public class ClientMainFrame extends JFrame {
    //显示当前用户
    public String username;

    public MyPanel myPanel;
    //提供与服务器通信的socket
    public Socket socket;

    //发送消息的线程
    public SendThread sendThread;
    //接收消息的线程
    public ReceiveThread receiveThread;

    //声明当前玩家用于接收玩家对象
    public Player currentPlayer;

    //扑克标签列表
    public List<PokerLabel> pokerLabels = new ArrayList<>();

    //抢地主标签
    public JLabel lordLabel;
    //"不叫"标签
    public JLabel passLabel;
    //计时器标签
    public JLabel timeLabel;
    //计时器线程
    public CountThread countThread;
    //是否地主
    public boolean isLord;
    //消息图标
    public JLabel messageLabel = new JLabel();
    //地主图标
    public JLabel lordIconLabel;
    //出牌图标
    public JLabel chuPaiLabel;
    //不出牌图标
    public JLabel buChuLabel;
    //出牌定时器线程
    public ChuPaiThread chuPaiThread; // 出牌定时器线程

    //存放选中的扑克列表
    public List<PokerLabel> selectedPokerLabels = new ArrayList<>();
    // 存放当前出牌的列表
    public List<PokerLabel> showOutPokerLabels = new ArrayList<>();
    // 选择的是出牌 true /不出牌 false
    public boolean isOut;
    // 上一个出牌的玩家id
    public int prevPlayerid = -1;

    //构造函数
    public ClientMainFrame(String username, Socket socket) {
        this.username = username;
        this.socket = socket;
        //设置主窗体
        this.setSize(1200, 700);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("欢迎" + username + "来到欢乐斗地主");

        //背景处理
        this.myPanel = new MyPanel();
        this.myPanel.setBounds(0, 0, 1200, 700);
        this.add(myPanel);

        //初始化窗口信息
        this.initWindow();

        //创建处理发送消息的线程并启动
        this.sendThread = new SendThread(socket, username);
        this.sendThread.start();
        //创建接收消息的线程并启动
        this.receiveThread = new ReceiveThread(socket, this);
        this.receiveThread.start();
    }

    //初始化窗口
    public void initWindow() {
        //创建消息标签
        messageLabel = new JLabel();

        String projectRoot = System.getProperty("user.dir") + "\\client\\images\\";
        chuPaiLabel = new JLabel();
        chuPaiLabel.setBounds(330, 350, 110, 53);
        chuPaiLabel.setIcon(new ImageIcon(projectRoot + "chu-pai-button.png"));
        chuPaiLabel.addMouseListener(new MyMouseEvent());
        chuPaiLabel.setVisible(false);
        this.myPanel.add(chuPaiLabel);

        buChuLabel = new JLabel();
        buChuLabel.setBounds(440, 350, 110, 53);
        buChuLabel.setIcon(new ImageIcon(projectRoot + "bu-chu-button.png"));
        buChuLabel.addMouseListener(new MyMouseEvent());
        buChuLabel.setVisible(false);
        this.myPanel.add(buChuLabel);

        timeLabel = new JLabel();
        timeLabel.setBounds(550, 350, 50, 50);
        timeLabel.setFont(new Font("Dialog", 0, 30));
        timeLabel.setForeground(Color.red);
        timeLabel.setVisible(false);
        this.myPanel.add(timeLabel);
    }

    //显示每一位玩家的扑克牌列表信息
    public void showAllPlayersInfo(List<Player> players) {
        for (int i = 0; i < players.size(); i++) {
            //判断是否为当前用户
            if (players.get(i).getName().equals(username)) {
                currentPlayer = players.get(i);
            }
        }
        //显示当前用户扑克牌列表
        List<Poker> pokers = currentPlayer.getPokers();
        //遍历扑克牌列表
        for (int j = 0; j < pokers.size(); j++) {
            Poker poker = pokers.get(j);
            //将当前玩家扑克进行显示 提供扑克牌标签
            PokerLabel pokerLabel = new PokerLabel(poker.getId(), poker.getName(), poker.getNum());
            //轮流显示每张扑克
            pokerLabel.turnUp();

            //把扑克牌画在面板上，用于在窗体显示扑克
            myPanel.add(pokerLabel);
            //把每张扑克标签存到标签列表
            pokerLabels.add(pokerLabel);
            //模拟动态显示效果
            myPanel.setComponentZOrder(pokerLabel, 0);

            //将牌逐渐显示出来
            GameUtil.move(pokerLabel, 300 + j * 30, 450);
        }
        //排序扑克列表
        Collections.sort(pokerLabels);
        //移动位置
        for (int i = 0; i < pokerLabels.size(); i++) {
            myPanel.setComponentZOrder(pokerLabels.get(i), 0);
            GameUtil.move(pokerLabels.get(i), 300 + i * 30, 450);
        }

        System.out.println(currentPlayer);
        if (currentPlayer.getId() == 0) {
            getLord();
        }
    }

    //抢地主方法
    public void getLord() {
        String projectRoot = System.getProperty("user.dir") + "\\client\\images\\";
        // 显示 叫地主、不叫和定时器
        lordLabel = new JLabel();
        lordLabel.setBounds(330, 400, 104, 46);
        lordLabel.setIcon(new ImageIcon(projectRoot + "jiao-di-zhu-button.png"));
        lordLabel.addMouseListener(new MyMouseEvent());
        myPanel.add(lordLabel);

        passLabel = new JLabel();
        passLabel.setBounds(450, 400, 104, 46);
        passLabel.setIcon(new ImageIcon(projectRoot + "bu-jiao-button.png"));
        passLabel.addMouseListener(new MyMouseEvent());
        myPanel.add(passLabel);

        //显示定时器图标
        timeLabel.setVisible(true);
        this.setVisible(true);
        //重绘
        this.repaint();
        //启动计时器线程
        countThread = new CountThread(20, this);
        countThread.start();
    }

    //显示出牌标签
    public void showChuPaiLabel() {
        if (prevPlayerid == currentPlayer.getId()) {
            //从窗口移除上次出牌列表
            for (int i = 0; i < showOutPokerLabels.size(); i++) {
                myPanel.remove(showOutPokerLabels.get(i));
            }
            showOutPokerLabels.clear();
        }
        //显示 出牌/不出 按钮 和定时器
        chuPaiLabel.setVisible(true);
        buChuLabel.setVisible(true);
        timeLabel.setVisible(true);

        this.repaint();
        chuPaiThread = new ChuPaiThread(30, this);
        chuPaiThread.start();
    }

    //显示消息（不抢/不出）
    public void showMessage(int playerid, int typeid) {
        messageLabel.setVisible(true);
        messageLabel.setBounds(500, 300, 129, 77);
        String projectRoot = System.getProperty("user.dir") + "\\client\\images\\";
        if (typeid == 1) {
            messageLabel.setIcon(new ImageIcon(projectRoot + "bu-qiang-bg.png"));
        } else if (typeid == 3) {
            messageLabel.setIcon(new ImageIcon(projectRoot + "bu-chu-bg.png"));
        }

        if (playerid == currentPlayer.getId()) {
            //当前玩家
            messageLabel.setLocation(400, 300);
        } else if ((playerid + 1) % 3 == currentPlayer.getId()) {
            //上家
            messageLabel.setLocation(300, 100);
        } else {
            //下家
            messageLabel.setLocation(800, 100);
        }
        myPanel.add(messageLabel);
        this.repaint();
    }

    //添加地主牌
    public void addLordPokers(List<Poker> lordPokers) {
        for (int i = 0; i < lordPokers.size(); i++) {
            Poker poker = lordPokers.get(i);
            PokerLabel pokerLabel = new PokerLabel(poker.getId(), poker.getName(), poker.getNum());
            pokerLabel.turnUp();
            this.pokerLabels.add(pokerLabel);
        }
        Collections.sort(this.pokerLabels);
        for (int i = 0; i < pokerLabels.size(); i++) {
            this.myPanel.add(pokerLabels.get(i));
            // 动态显示牌
            this.myPanel.setComponentZOrder(pokerLabels.get(i), 0);
            GameUtil.move(pokerLabels.get(i), 300 + 30 * i, 450);
        }
        currentPlayer.getPokers().addAll(lordPokers);
    }

    //显示地主图标
    public void showLordIcon(int playerid) {
        lordIconLabel = new JLabel();
        String projectRoot = System.getProperty("user.dir") + "\\client\\images\\";
        lordIconLabel.setIcon(new ImageIcon(projectRoot + "lord.png"));
        lordIconLabel.setSize(60, 89);

        //根据玩家id显示地主图标到具体位置
        if (playerid == currentPlayer.getId()) {
            lordIconLabel.setLocation(200, 450);
        } else if ((playerid + 1) % 3 == currentPlayer.getId()) {
            lordIconLabel.setLocation(200, 100);
        } else {
            lordIconLabel.setLocation(950, 100);
        }
        myPanel.add(lordIconLabel);
        this.repaint();
    }

    //给扑克牌添加单击事件
    public void addClickEventToPoker() {
        for (int i = 0; i < pokerLabels.size(); i++) {
            pokerLabels.get(i).addMouseListener(new PokerEvent());
        }
    }

    //显示出牌列表
    public void showOutPokerList(int playerid, List<Poker> outPokers) {
        //移除之前出牌的列表
        for (int i = 0; i < showOutPokerLabels.size(); i++) {
            myPanel.remove(showOutPokerLabels.get(i));
        }
        showOutPokerLabels.clear();
        //显示当前出牌列表
        for (int i = 0; i < outPokers.size(); i++) {
            Poker poker = outPokers.get(i);
            PokerLabel pokerLabel = new PokerLabel(poker.getId(), poker.getName(), poker.getNum());

            if (playerid == currentPlayer.getId()) {
                pokerLabel.setLocation(400 + 30 * i, 300);
            } else if ((playerid + 1) % 3 == currentPlayer.getId()) {
                pokerLabel.setLocation(200 + 30 * i, 100);
            } else {
                pokerLabel.setLocation(700 + 30 * i, 100);
            }

            pokerLabel.turnUp();
            myPanel.add(pokerLabel);
            showOutPokerLabels.add(pokerLabel);
            myPanel.setComponentZOrder(pokerLabel, 0);
        }
        this.repaint();
    }

    //将出的牌从当前玩家的扑克列表中移除
    public void removeOutPokerFromPokerList() {
        //从当前玩家扑克列表移除
        pokerLabels.removeAll(selectedPokerLabels);

        //从面板移除
        for (int i = 0; i < selectedPokerLabels.size(); i++) {
            myPanel.remove(selectedPokerLabels.get(i));
        }
        //重新排序和定位剩余扑克
        for (int i = 0; i < pokerLabels.size(); i++) {
            myPanel.setComponentZOrder(pokerLabels.get(i), 0);
            GameUtil.moveWithNoSleep(pokerLabels.get(i), 300 + 30 * i, 450);
        }
        //清空选择扑克牌列表
        selectedPokerLabels.clear();
        this.repaint();
    }

    //游戏结束
    public void gameOver()  {
        myPanel.removeAll();
        this.repaint();
        try {
            this.socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.countThread.setRun(false);
        this.chuPaiThread.setRun(false);
        this.sendThread.setRun(false);
        this.receiveThread.setRun(false);
    }

    class MyMouseEvent implements MouseListener {
        @Override
        public void mouseClicked(MouseEvent e) {
            //点击叫地主
            if (e.getSource().equals(lordLabel)) {
                //停止计时器
                countThread.setRun(false);
                isLord = true;
                lordLabel.setVisible(false);
                passLabel.setVisible(false);
                timeLabel.setVisible(false);
            }
            //点击不抢
            if (e.getSource().equals(passLabel)) {
                countThread.setRun(false);
                isLord = false;
                lordLabel.setVisible(false);
                passLabel.setVisible(false);
                timeLabel.setVisible(false);
            }
            //点击出牌
            if (e.getSource().equals(chuPaiLabel)) {
                //需要判断牌型
                PokerType pokerType = PokerRule.checkPokerType(selectedPokerLabels);

                //判断是否符合牌型
                if (pokerType.equals(PokerType.p_error) == false) {
                    //符合牌型，判断是否比上家大/上家是否是自己
                    if (prevPlayerid == -1 ||
                            prevPlayerid == currentPlayer.getId() ||
                            PokerRule.isBigger(showOutPokerLabels, selectedPokerLabels)) {
                        isOut = true;
                        //停止计时器
                        chuPaiThread.setRun(false);
                        chuPaiLabel.setVisible(false);
                        buChuLabel.setVisible(false);
                        timeLabel.setVisible(false);
                    }else{
                        JOptionPane.showMessageDialog(null, "您的牌无法打过上家，请重新选择");
                    }
                } else {
                    //不符合牌型
                    JOptionPane.showMessageDialog(null, "您的牌型不匹配，请重新选择");
                }
            }

            //点击不出
            if (e.getSource().equals(buChuLabel)) {
                isOut = false;
                //停止计时器
                chuPaiThread.setRun(false);
                chuPaiLabel.setVisible(false);
                buChuLabel.setVisible(false);
                timeLabel.setVisible(false);
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }
    }

    //扑克牌事件监听器类
    class PokerEvent implements MouseListener {
        @Override
        public void mouseClicked(MouseEvent e) {
            PokerLabel pokerLabel = (PokerLabel) e.getSource();
            // 之前选择过则取消选择(设置选中属性为false 回到原位,从选择的扑克牌列表中移除)
            if (pokerLabel.isSelected()) {
                pokerLabel.setSelected(false);
                pokerLabel.setLocation(pokerLabel.getX(), pokerLabel.getY() + 30);
                selectedPokerLabels.remove(pokerLabel);
            }
            // 之前未选择则选中(设置选中属性为true 往上移动,添加到选择的扑克牌列表中)
            else {
                pokerLabel.setSelected(true);
                pokerLabel.setLocation(pokerLabel.getX(), pokerLabel.getY() - 30);
                selectedPokerLabels.add(pokerLabel);
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }
    }
}









